﻿using System;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Threading;
using PSE.Deployment.SetupBase.Configuration;

namespace PSE.Deployment.SetupBase
{
    public class ApplicationBase : System.Windows.Application
    {
        public bool CheckCurrentProcess { get; set; }

        public ApplicationBase()
        {
            this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
            this.Startup += new StartupEventHandler(OnApplicationStartup);
            this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(OnDispatcherUnhandledException);
            this.CheckCurrentProcess = true;
        }

        protected virtual void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            string message = null;

            try
            {
                System.Diagnostics.EventLog.WriteEntry("PSE Setup", e.Exception.ToString(), EventLogEntryType.Error);

                message = e.Exception.Message;
            }
            catch
            {
                message = e.Exception.ToString();
            }

            MessageBox.Show(message, "Erro", MessageBoxButton.OK, MessageBoxImage.Error);

            e.Handled = true;

            this.CloseApplication(-1);
        }

        protected virtual void OnApplicationStartup(object sender, StartupEventArgs e)
        {
            LoadTheme();
        }

        protected bool IsCurrentProcessRunning()
        {
            Process[] procs = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);

            if (procs.Length > 1 && this.CheckCurrentProcess)
            {
                MessageBox.Show("O Processo não pode ser aberto pois já existe uma instância em execução.", "Atenção", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }

            return procs.Length > 1 && this.CheckCurrentProcess;
        }

        protected void LoadTheme()
        {
            SetupConfigurationSection setupSection = System.Configuration.ConfigurationManager.GetSection("setupConfiguration") as SetupConfigurationSection;

            if (setupSection == null)
                throw new ConfigurationErrorsException("The section 'setupConfiguration' don't exists in the configuration file.");

            foreach (AssemblyElement assemblyInfo in setupSection.Theme.Assemblies)
            {
                if (string.IsNullOrEmpty(assemblyInfo.Assembly))
                    throw new ArgumentNullException("setupSection.Theme.Assembly.Assembly");

                if (string.IsNullOrEmpty(assemblyInfo.Class))
                    throw new ArgumentNullException("setupSection.Theme.Assembly.Class");

                LoadResource(assemblyInfo);
            }
        }

        protected void LoadResource(AssemblyElement assemblyInfo)
        {
            Assembly resource = Assembly.Load(assemblyInfo.Assembly);
            string nmspace = resource.GetName().Name;

            Uri dictionaryUri = new Uri(nmspace + @";;;component\" + assemblyInfo.Class, UriKind.Relative);

            ResourceDictionary dictionary = System.Windows.Application.LoadComponent(dictionaryUri) as ResourceDictionary;

            System.Windows.Application.Current.Resources.MergedDictionaries.Add(dictionary);

            if (dictionary != null)
            {
                ReloadResources(nmspace, dictionary);
            }
        }

        private void ReloadResources(string theme, ResourceDictionary dic)
        {
            foreach (ResourceDictionary child in dic.MergedDictionaries)
            {
                this.ReloadResources(theme, child);

                if (child.Source != null)
                {
                    Uri dictionary = new Uri(theme + @";;;component\" + child.Source.ToString(), UriKind.Relative);
                    System.Windows.Application.Current.Resources.MergedDictionaries.Add((ResourceDictionary)System.Windows.Application.LoadComponent(dictionary));
                }
            }
        }

        protected virtual void CloseApplication(int exitCode)
        {
            this.Shutdown(exitCode);
        }
    }
}